package controller

import (
	"context"
	"mpps/tools/auth"
	common "mpps/tools/common"
	"mpps/tools/config"
	"mpps/web/models"

	UserLogin "mpps/services/srv-UserLogin/proto"
	UserLogout "mpps/services/srv-UserLogout/proto"
	UserRefreshToken "mpps/services/srv-UserRefreshToken/proto"
	UserRegister "mpps/services/srv-UserRegister/proto"

	"github.com/gin-gonic/gin"
)

type UserController interface {
	UserRegister(c *gin.Context)
	UserLogin(c *gin.Context)
	UserLogout(c *gin.Context)
	UserRefreshToken(c *gin.Context)
}

type User struct {
	UserController
	UserRegisterService     UserRegister.UserRegisterService
	UserLoginService        UserLogin.UserLoginService
	UserLogoutService       UserLogout.UserLogoutService
	UserRefreshTokenService UserRefreshToken.UserRefreshTokenService
}

func NewUserController() UserController {
	return &User{
		UserRegisterService:     UserRegister.NewUserRegisterService(config.UserRegisterSrv, common.GetMicroClient()),
		UserLoginService:        UserLogin.NewUserLoginService(config.UserLoginSrv, common.GetMicroClient()),
		UserLogoutService:       UserLogout.NewUserLogoutService(config.UserLogoutSrv, common.GetMicroClient()),
		UserRefreshTokenService: UserRefreshToken.NewUserRefreshTokenService(config.UserRefreshTokenSrv, common.GetMicroClient()),
	}
}

// @Summary 	注册
// @Description User
// @Tags 		用户
// @Accept 		json
// @Param 		body参数 body models.UserReq true "请求body"
// @Success 	200 {object} models.Resp
// @Failure 	500 {object} models.Resp
// @Router 		/v1/user/register [post]
func (m *User) UserRegister(c *gin.Context) {
	body := models.UserReq{}
	err := c.BindJSON(&body)
	if err != nil {
		models.WriteHttpFail(c, common.ErrParamsValidation)
		return
	}
	_, err = m.UserRegisterService.Call(context.Background(), &UserRegister.Request{
		Email:    body.Email,
		Password: body.Password,
	})
	if err != nil {
		models.WriteHttpFail(c, common.ErrPostCreateUser)
		return
	}
	models.WriteHttpCodeSucc(c, common.OK)
}

// @Summary 	登录
// @Description User
// @Tags 		用户
// @Accept 		json
// @Param 		body参数 body models.UserReq true "请求body"
// @Success 	200 {object} models.Resp
// @Failure 	500 {object} models.Resp
// @Router 		/v1/user/login [post]
func (m *User) UserLogin(c *gin.Context) {
	body := models.UserReq{}
	err := c.BindJSON(&body)
	if err != nil {
		models.WriteHttpFail(c, common.ErrParamsValidation)
		return
	}
	pbRsp, err := m.UserLoginService.Call(context.Background(), &UserLogin.Request{
		Email:    body.Email,
		Password: body.Password,
	})
	if err != nil {
		models.WriteHttpFail(c, common.ErrPostLogin)
		return
	}
	models.WriteHttpSucc(c, pbRsp)
}

// @Summary 	退出登录
// @Description User
// @Tags 		用户
// @Accept 		json
// @Param       token	   header	string  			 true  "token"
// @Param 		body参数	body	 models.UserLogoutReq true	"请求body"
// @Success 	200 {object} models.Resp
// @Failure 	500 {object} models.Resp
// @Router 		/v1/user/logout [post]
func (m *User) UserLogout(c *gin.Context) {
	body := models.UserLogoutReq{}
	err := c.BindJSON(&body)
	if err != nil {
		models.WriteHttpFail(c, common.ErrParamsValidation)
		return
	}
	pbRsp, err := m.UserLogoutService.Call(auth.WithToken(c), &UserLogout.Request{
		AccessToken:  body.AccessToken,
		RefreshToken: body.RefreshToken,
	})
	if err != nil {
		models.WriteHttpFail(c, common.ErrPostLogout)
		return
	}
	models.WriteHttpSucc(c, pbRsp)
}

// @Summary 	续租token
// @Description User
// @Tags 		用户
// @Accept 		json
// @Param 		body参数 body models.RefreshTokenReq true "请求body"
// @Success 	200 {object} models.Resp
// @Failure 	500 {object} models.Resp
// @Router 		/v1/user/refreshToken [post]
func (m *User) UserRefreshToken(c *gin.Context) {
	body := models.RefreshTokenReq{}
	err := c.BindJSON(&body)
	if err != nil {
		models.WriteHttpFail(c, common.ErrParamsValidation)
		return
	}
	pbRsp, err := m.UserRefreshTokenService.Call(context.Background(), &UserRefreshToken.Request{
		AccessToken:  body.AccessToken,
		RefreshToken: body.RefreshToken,
	})
	if err != nil {
		models.WriteHttpFail(c, common.ErrAuth)
		return
	}
	models.WriteHttpSucc(c, pbRsp)
}
